﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Tokenizer.VBTokenizer
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using System.Collections.Generic;
using System.Globalization;
using System.Web.Razor.Parser;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Text;
using System.Web.Razor.Tokenizer.Symbols;

namespace System.Web.Razor.Tokenizer
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Allows an application to break a VB symbol into tokens.</summary>
  public class VBTokenizer : System.Web.Razor.Tokenizer.Tokenizer<VBSymbol, VBSymbolType>
  {
    private static Dictionary<char, VBSymbolType> _operatorTable = new Dictionary<char, VBSymbolType>()
    {
      {
        '_',
        VBSymbolType.LineContinuation
      },
      {
        '(',
        VBSymbolType.LeftParenthesis
      },
      {
        ')',
        VBSymbolType.RightParenthesis
      },
      {
        '[',
        VBSymbolType.LeftBracket
      },
      {
        ']',
        VBSymbolType.RightBracket
      },
      {
        '{',
        VBSymbolType.LeftBrace
      },
      {
        '}',
        VBSymbolType.RightBrace
      },
      {
        '!',
        VBSymbolType.Bang
      },
      {
        '#',
        VBSymbolType.Hash
      },
      {
        ',',
        VBSymbolType.Comma
      },
      {
        '.',
        VBSymbolType.Dot
      },
      {
        ':',
        VBSymbolType.Colon
      },
      {
        '?',
        VBSymbolType.QuestionMark
      },
      {
        '&',
        VBSymbolType.Concatenation
      },
      {
        '*',
        VBSymbolType.Multiply
      },
      {
        '+',
        VBSymbolType.Add
      },
      {
        '-',
        VBSymbolType.Subtract
      },
      {
        '/',
        VBSymbolType.Divide
      },
      {
        '\\',
        VBSymbolType.IntegerDivide
      },
      {
        '^',
        VBSymbolType.Exponentiation
      },
      {
        '=',
        VBSymbolType.Equal
      },
      {
        '<',
        VBSymbolType.LessThan
      },
      {
        '>',
        VBSymbolType.GreaterThan
      },
      {
        '$',
        VBSymbolType.Dollar
      }
    };

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Initializes a new instance of the <see cref="T:System.Web.Razor.Tokenizer.VBTokenizer" /> class.</summary>
    /// <param name="source">The source of text.</param>
    public VBTokenizer(ITextDocument source)
      : base(source)
    {
      this.CurrentState = new StateMachine<VBSymbol>.State(this.Data);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the start state of the machine.</summary>
    /// <returns>The start state of the machine.</returns>
    protected override StateMachine<VBSymbol>.State StartState => new StateMachine<VBSymbol>.State(this.Data);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the razor type comment of the <see cref="T:System.Web.Razor.Tokenizer.Symbols.VBSymbolType" />.</summary>
    /// <returns>The razor type comment of the <see cref="T:System.Web.Razor.Tokenizer.Symbols.VBSymbolType" />.</returns>
    public override VBSymbolType RazorCommentType => VBSymbolType.RazorComment;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the transition style of the VB symbol.</summary>
    /// <returns>The transition style of the VB symbol.</returns>
    public override VBSymbolType RazorCommentTransitionType => VBSymbolType.RazorCommentTransition;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the VB symbol type.</summary>
    /// <returns>The VB symbol type.</returns>
    public override VBSymbolType RazorCommentStarType => VBSymbolType.RazorCommentStar;

    internal static IEnumerable<VBSymbol> Tokenize(string content)
    {
      using (SeekableTextReader reader = new SeekableTextReader(content))
      {
        VBTokenizer tok = new VBTokenizer((ITextDocument) reader);
        VBSymbol vbSymbol;
        while ((vbSymbol = tok.NextSymbol()) != null)
          yield return vbSymbol;
        tok = (VBTokenizer) null;
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Creates a domain of symbols.</summary>
    /// <returns>A domain of symbols.</returns>
    /// <param name="start">The source location.</param>
    /// <param name="content">The content value.</param>
    /// <param name="type">The <see cref="T:System.Web.Razor.Tokenizer.Symbols.VBSymbolType" />.</param>
    /// <param name="errors">The razor error.</param>
    protected override VBSymbol CreateSymbol(
      SourceLocation start,
      string content,
      VBSymbolType type,
      IEnumerable<RazorError> errors)
    {
      return new VBSymbol(start, content, type, errors);
    }

    private StateMachine<VBSymbol>.StateResult Data()
    {
      if (ParserHelpers.IsNewLine(this.CurrentCharacter))
      {
        int num = this.CurrentCharacter == '\r' ? 1 : 0;
        this.TakeCurrent();
        if (num != 0 && this.CurrentCharacter == '\n')
          this.TakeCurrent();
        return this.Stay(this.EndSymbol(VBSymbolType.NewLine));
      }
      if (ParserHelpers.IsWhitespace(this.CurrentCharacter))
      {
        this.TakeUntil((Func<char, bool>) (c => !ParserHelpers.IsWhitespace(c)));
        return this.Stay(this.EndSymbol(VBSymbolType.WhiteSpace));
      }
      if (VBHelpers.IsSingleQuote(this.CurrentCharacter))
      {
        this.TakeCurrent();
        return this.CommentBody();
      }
      if (this.IsIdentifierStart())
        return this.Identifier();
      if (char.IsDigit(this.CurrentCharacter))
        return this.DecimalLiteral();
      if (this.CurrentCharacter == '&')
      {
        switch (char.ToLower(this.Peek(), CultureInfo.InvariantCulture))
        {
          case 'h':
            return this.HexLiteral();
          case 'o':
            return this.OctLiteral();
        }
      }
      else
      {
        if (this.CurrentCharacter == '.' && char.IsDigit(this.Peek()))
          return this.FloatingPointLiteralEnd();
        if (VBHelpers.IsDoubleQuote(this.CurrentCharacter))
        {
          this.TakeCurrent();
          return this.Transition(new StateMachine<VBSymbol>.State(this.QuotedLiteral));
        }
        if (this.AtDateLiteral())
          return this.DateLiteral();
        if (this.CurrentCharacter == '@')
        {
          this.TakeCurrent();
          if (this.CurrentCharacter == '*')
            return this.Transition(this.EndSymbol(VBSymbolType.RazorCommentTransition), new StateMachine<VBSymbol>.State(((System.Web.Razor.Tokenizer.Tokenizer<VBSymbol, VBSymbolType>) this).AfterRazorCommentTransition));
          return this.CurrentCharacter == '@' ? this.Transition(this.EndSymbol(VBSymbolType.Transition), (StateMachine<VBSymbol>.State) (() =>
          {
            this.TakeCurrent();
            return this.Transition(this.EndSymbol(VBSymbolType.Transition), new StateMachine<VBSymbol>.State(this.Data));
          })) : this.Stay(this.EndSymbol(VBSymbolType.Transition));
        }
      }
      return this.Stay(this.EndSymbol(this.Operator()));
    }

    private StateMachine<VBSymbol>.StateResult DateLiteral()
    {
      this.TakeCurrent();
      this.TakeUntil((Func<char, bool>) (c => c == '#' || ParserHelpers.IsNewLine(c)));
      if (this.CurrentCharacter == '#')
        this.TakeCurrent();
      return this.Stay(this.EndSymbol(VBSymbolType.DateLiteral));
    }

    private bool AtDateLiteral()
    {
      if (this.CurrentCharacter != '#')
        return false;
      int position = this.Source.Position;
      try
      {
        this.MoveNext();
        while (ParserHelpers.IsWhitespace(this.CurrentCharacter))
          this.MoveNext();
        return char.IsDigit(this.CurrentCharacter);
      }
      finally
      {
        this.Source.Position = position;
      }
    }

    private StateMachine<VBSymbol>.StateResult QuotedLiteral()
    {
      this.TakeUntil((Func<char, bool>) (c => VBHelpers.IsDoubleQuote(c) || ParserHelpers.IsNewLine(c)));
      if (VBHelpers.IsDoubleQuote(this.CurrentCharacter))
      {
        this.TakeCurrent();
        if (VBHelpers.IsDoubleQuote(this.CurrentCharacter))
        {
          this.TakeCurrent();
          return this.Stay();
        }
      }
      VBSymbolType type = VBSymbolType.StringLiteral;
      if (char.ToLowerInvariant(this.CurrentCharacter) == 'c')
      {
        this.TakeCurrent();
        type = VBSymbolType.CharacterLiteral;
      }
      return this.Transition(this.EndSymbol(type), new StateMachine<VBSymbol>.State(this.Data));
    }

    private StateMachine<VBSymbol>.StateResult DecimalLiteral()
    {
      this.TakeUntil((Func<char, bool>) (c => !char.IsDigit(c)));
      char lowerInvariant = char.ToLowerInvariant(this.CurrentCharacter);
      if (VBTokenizer.IsFloatTypeSuffix(lowerInvariant) || lowerInvariant == '.' || lowerInvariant == 'e')
        return this.FloatingPointLiteralEnd();
      this.TakeIntTypeSuffix();
      return this.Stay(this.EndSymbol(VBSymbolType.IntegerLiteral));
    }

    private static bool IsFloatTypeSuffix(char chr)
    {
      chr = char.ToLowerInvariant(chr);
      return chr == 'f' || chr == 'r' || chr == 'd';
    }

    private StateMachine<VBSymbol>.StateResult FloatingPointLiteralEnd()
    {
      if (this.CurrentCharacter == '.')
      {
        this.TakeCurrent();
        this.TakeUntil((Func<char, bool>) (c => !char.IsDigit(c)));
      }
      if (char.ToLowerInvariant(this.CurrentCharacter) == 'e')
      {
        this.TakeCurrent();
        if (this.CurrentCharacter == '+' || this.CurrentCharacter == '-')
          this.TakeCurrent();
        this.TakeUntil((Func<char, bool>) (c => !char.IsDigit(c)));
      }
      if (VBTokenizer.IsFloatTypeSuffix(this.CurrentCharacter))
        this.TakeCurrent();
      return this.Stay(this.EndSymbol(VBSymbolType.FloatingPointLiteral));
    }

    private StateMachine<VBSymbol>.StateResult HexLiteral()
    {
      this.TakeCurrent();
      this.TakeCurrent();
      this.TakeUntil((Func<char, bool>) (c => !ParserHelpers.IsHexDigit(c)));
      this.TakeIntTypeSuffix();
      return this.Stay(this.EndSymbol(VBSymbolType.IntegerLiteral));
    }

    private StateMachine<VBSymbol>.StateResult OctLiteral()
    {
      this.TakeCurrent();
      this.TakeCurrent();
      this.TakeUntil((Func<char, bool>) (c => !VBHelpers.IsOctalDigit(c)));
      this.TakeIntTypeSuffix();
      return this.Stay(this.EndSymbol(VBSymbolType.IntegerLiteral));
    }

    private VBSymbolType Operator()
    {
      char currentCharacter = this.CurrentCharacter;
      this.TakeCurrent();
      VBSymbolType vbSymbolType;
      return VBTokenizer._operatorTable.TryGetValue(currentCharacter, out vbSymbolType) ? vbSymbolType : VBSymbolType.Unknown;
    }

    private void TakeIntTypeSuffix()
    {
      if (char.ToLowerInvariant(this.CurrentCharacter) == 'u')
        this.TakeCurrent();
      if (!VBTokenizer.IsIntegerSuffix(this.CurrentCharacter))
        return;
      this.TakeCurrent();
    }

    private static bool IsIntegerSuffix(char chr)
    {
      chr = char.ToLowerInvariant(chr);
      return chr == 's' || chr == 'i' || chr == 'l';
    }

    private StateMachine<VBSymbol>.StateResult CommentBody()
    {
      this.TakeUntil(new Func<char, bool>(ParserHelpers.IsNewLine));
      return this.Stay(this.EndSymbol(VBSymbolType.Comment));
    }

    private StateMachine<VBSymbol>.StateResult Identifier()
    {
      bool flag = false;
      if (this.CurrentCharacter == '[')
      {
        this.TakeCurrent();
        flag = true;
      }
      this.TakeUntil((Func<char, bool>) (c => !ParserHelpers.IsIdentifierPart(c)));
      if (flag && this.CurrentCharacter == ']')
        this.TakeCurrent();
      VBKeyword? keyword = VBKeywordDetector.GetKeyword(this.Buffer.ToString());
      VBKeyword? nullable = keyword;
      VBKeyword vbKeyword = VBKeyword.Rem;
      if (nullable.GetValueOrDefault() == vbKeyword & nullable.HasValue)
        return this.CommentBody();
      VBSymbol output = new VBSymbol(this.CurrentStart, this.Buffer.ToString(), !keyword.HasValue ? VBSymbolType.Identifier : VBSymbolType.Keyword)
      {
        Keyword = keyword
      };
      this.StartSymbol();
      return this.Stay(output);
    }

    private bool IsIdentifierStart()
    {
      if (this.CurrentCharacter == '_')
        return ParserHelpers.IsIdentifierPart(this.Peek());
      return this.CurrentCharacter == '[' ? ParserHelpers.IsIdentifierPart(this.Peek()) : ParserHelpers.IsIdentifierStart(this.CurrentCharacter);
    }
  }
}
